home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
bbsutil
/
dlx70bbs.zip
/
DLX70SRC.ZIP
/
XMODEM.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1994-01-19
|
16KB
|
447 lines
{$debug-}
{$line-}
{$include: 'types.int'}
{$include: 'globals.int'}
{$include: 'utils.int'}
{$include: 'xmodem.int'}
IMPLEMENTATION OF xmodem;
USES types,globals,utils;
{DLX Bulletin Board System V7.0
FREEWARE NOTICE
DLX V7.0 is placed in the public domain by its author, Richard Gillmann.
Anyone who wishes to may run the program, copy it, or modify it for
any purpose, including commercial gain.}
{***INTERFACE TO THE PASASM ASSEMBLER UTILITIES PACKAGE***}
{$include: 'pasasm.int'}
{***INTERFACE TO THE COM_PAX2 ASYNCHRONOUS COMMUNICATIONS PACKAGE***}
{$include: 'com_pax2.int'}
{***Interface to MS Pascal library***}
function allmqq(wants : word) : adsmem; EXTERN;
const
soh = chr(16#01); {Ctrl-A = start of 128 byte block}
stx = chr(16#02); {Ctrl-B = start of 1024 byte block}
eot = chr(16#04); {Ctrl-D = end of transmit}
ack = chr(16#06); {Ctrl-F = acknowledge}
bs = chr(16#08); {Ctrl-H = backspace}
nak = chr(16#15); {Ctrl-U = negative acknowledge}
can = chr(16#18); {Ctrl-X = cancel}
ctrl_z = chr(16#1A); {MS DOS end of file marker}
filler = ctrl_z; {use this character to pad out short blocks}
max_errs = 20; {this many protocol errors -> cancel the thing}
function newbpara {bpara};
var
b : bpara;
begin
if bavail<>RETYPE(bpara,nill) then
[newbpara:=bavail; bavail:=bavail^.link]
else
[b:=allmqq(sizeof(bavail^)); {don't fail if no mem}
if b.r<=1
then b:=RETYPE(bpara,nill)
else lhc:=lhc+sizeof(bavail^)+2;
newbpara:=b];
end {newbpara};
procedure disbpara{b : bpara};
begin
b^.link:=bavail;
bavail:=b;
end {disbpara};
procedure cancel;
begin
send(can);
send(can);
send(can);
send(bs);
send(bs);
send(bs);
end {cancel};
{Called from cleanup code, in case user hangs up during a transfer.
Only called when state2<>0}
procedure xcancel;
var
str : lstring(64);
begin
if q[wx].handle>0 then
[if q[wx].bflag {downloading} then
mail_close(q[wx].handle)
else
[copylst(q[wx].pathname,str); concat(str,'\');
konkat(str,q[wx].filename); mail_delete(str)]];
q[wx].handle:=0;
if w^[wx].file_locked<>nill then w^[wx].file_locked^.msg:=null;
binary_mode(0);
w^[wx].strx:=null;
end {xcancel};
{THE SENDER}
procedure xtransmit; {download from board to caller}
var
next_state2 : integer;
str : lstring(64);
i,j : integer;
chksum : word;
i4 : integer4;
flag : boolean;
begin
next_state2:=q[wx].state2+1;
case q[wx].state2 of
{open the file we're going to send}
1 : [binary_mode(1);
q[wx].count4:=0; q[wx].index:=0; q[wx].count:=0; q[wx].dos_err:=0;
copylst(q[wx].pathname,str); concat(str,'\');
concat(str,q[wx].filename);
{file locking done before we get here}
if (q[wx].xfermode and f128)<>0 then
[w^[wx].strx.len:=128;
fillsc(ads w^[wx].strx[1],128,filler)]
else
fillsc(ads q[wx].buffer^.data[1],1024,filler);
q[wx].handle:=xopen(0,str);
if q[wx].handle<=0 then
[q[wx].flag:=false; q[wx].count:=-q[wx].handle;
q[wx].dos_err:=-q[wx].handle; q[wx].handle:=0; next_state2:=665];
w^[wx].clock_target:=jt];
{wait for command from receiver}
2 : [i4:=jt-w^[wx].clock_target;
if i4<0 then i4:=i4+one_day;
if i4>60 then
[q[wx].flag:=false; q[wx].count:=0; next_state2:=665]
else if r_count=0 then
next_state2:=2];
{looking for nak or C or G to begin download}
3 : case receive of
can : {cancel}
[q[wx].flag:=false; q[wx].count:=0; next_state2:=665];
nak : {please send block w/checksum}
[q[wx].xfermode := q[wx].xfermode and (not fCrc);
next_state2:=6];
'C' : {please send block w/CRC}
[q[wx].xfermode := q[wx].xfermode or fCrc;
next_state2:=6];
'G' : {please send block w/CRC and don't expect an ack in response}
[q[wx].xfermode := q[wx].xfermode or fCrc or fNak;
next_state2:=6];
otherwise next_state2:=2;
end {case};
{wait for response to end of transmission}
4 : [i4:=jt-w^[wx].clock_target;
if i4<0 then i4:=i4+one_day;
if i4>60 then
[q[wx].flag:=false; q[wx].count:=0; next_state2:=665]
else if r_count=0 then
next_state2:=4];
{looking for ack}
5 : case receive of
can : [q[wx].flag:=false; q[wx].count:=0; next_state2:=665];
ack : [q[wx].flag:=true; q[wx].count:=0; next_state2:=665];
nak,'C' : [while r_count>0 do eval(receive);
send(eot);
next_state2:=4];
otherwise next_state2:=4;
end {case};
{read next packet's data from file}
6 : [q[wx].index:=(q[wx].index+1) mod 256;
if (q[wx].xfermode and f128)<>0 then
[w^[wx].strx.len:=128;
fillsc(ads w^[wx].strx[1],128,filler);
i:=xread(q[wx].handle,ads w^[wx].strx[1],128)]
else
[fillsc(ads q[wx].buffer^.data[1],1024,filler);
i:=xread(q[wx].handle,ads q[wx].buffer^.data[1],1024)];
if i<0 then
[q[wx].flag:=false; q[wx].count:=-i; q[wx].dos_err:=-i;
next_state2:=665]
else if i=0 then {end of file}
[send(eot);
w^[wx].clock_target:=jt; next_state2:=4]
else
q[wx].bindex:=0];
{send packet header}
7 : [if (q[wx].xfermode and f128)<>0 then
send(soh)
else
send(stx);
send(chr(q[wx].index));
send(chr(255-q[wx].index));
q[wx].crc:=0];
{send packet data}
8 : if (q[wx].xfermode and f128)<>0 then
[chksum:=0;
for i:=1 to 128 do
[send(w^[wx].strx[i]);
if (q[wx].xfermode and fCrc)<>0
then crc_16(w^[wx].strx[i],chksum)
else chksum:=chksum+wrd(w^[wx].strx[i])];
if (q[wx].xfermode and fCrc)<>0 then
send(chr(hibyte(chksum)));
send(chr(lobyte(chksum)))]
else if s_free>10 then
[j:=s_free-5;
if j>1024-q[wx].bindex then j:=1024-q[wx].bindex;
for i:=1 to j do
[send(q[wx].buffer^.data[q[wx].bindex+i]);
crc_16(q[wx].buffer^.data[q[wx].bindex+i],q[wx].crc)];
q[wx].bindex:=q[wx].bindex+j;
if q[wx].bindex=1024 then
[send(chr(hibyte(q[wx].crc)));
send(chr(lobyte(q[wx].crc)))]
else
next_state2:=8]
else
next_state2:=8;
{when packet completely sent, purge the input buffer}
9 : if (q[wx].xfermode and fNak)<>0 then
[if (q[wx].xfermode and f128)<>0
then q[wx].count4 := q[wx].count4 + 128
else q[wx].count4 := q[wx].count4 + 1024;
next_state2:=6]
else if s_working>0 then
[while r_count>0 do eval(receive);
next_state2:=9]
else
w^[wx].clock_target:=jt;
{wait for response to packet}
10 : [i4:=jt-w^[wx].clock_target;
if i4<0 then i4:=i4+one_day;
if i4>60 then
[q[wx].flag:=false; q[wx].count:=0; next_state2:=665]
else if r_count=0 then
next_state2:=10];
{looking for an ack}
11 : case receive of
can : [q[wx].flag:=false; q[wx].count:=0; next_state2:=665];
ack : [if (q[wx].xfermode and f128)<>0
then q[wx].count4:=q[wx].count4+128
else q[wx].count4:=q[wx].count4+1024;
next_state2:=6];
nak : next_state2:=7;
otherwise next_state2:=10;
end {case};
{finish up}
665 : [if q[wx].handle>0 then
mail_close(q[wx].handle);
q[wx].handle:=0;
if w^[wx].file_locked<>nill then w^[wx].file_locked^.msg:=null;
binary_mode(0); w^[wx].strx:=null];
end {case};
q[wx].state2:=next_state2;
end {xtransmit};
{